package edu.pku.sei.autounit.plugin;

import java.io.ByteArrayInputStream;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.FileEditorInput;

import edu.pku.sei.autounit.core.JUnitGenerator;
import edu.pku.sei.autounit.reflect.Class;
import edu.pku.sei.autounit.reflect.jdt.JDTTypeFactory;
import edu.pku.sei.autounit.util.Log;

public class GenForClass implements IObjectActionDelegate {

	private Shell shell;
	private IType type;
	private IProject project;
	private IJavaProject javaProject;
	
	

	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
		shell = targetPart.getSite().getShell();
	}

	public void run(IAction action) {
		try {
			if(type.isEnum()||type.isInterface()){
				MessageDialog.openInformation(shell, "", "This item is no need to be test"); 
				return ;
			}
		} catch (JavaModelException e) {
			Log.gotUnexpectedExection("GenForClass", "run","", e);
		}
		try{
			generatedCode();
		}catch(Throwable e){
			MessageDialog.openInformation(shell,"ERROR",e.toString()); 
		}
			
	}

	public void selectionChanged(IAction action, ISelection selection) {

		if (selection instanceof TreeSelection) {
			TreeSelection ts = (TreeSelection) selection;
			type = (IType) ts.getFirstElement();
			javaProject = type.getJavaProject();
			project = javaProject.getProject();
		}
		
		else{
			Log.info("didn't deal with "+selection.getClass().getName());
		}
	}

	

	private void generatedCode() {
		JDTTypeFactory t = new JDTTypeFactory();
		Class c = (Class) t.getType(type);
		String packageName = type.getPackageFragment().getElementName();
		String className = type.getTypeQualifiedName();
		className = "Test" + className;

		String pathString = InitProject.CODE_FOLDER;
		for (String s : packageName.split("[\\.]")) {
			pathString = pathString + "/" + s;
			IFolder f = project.getFolder(new Path(pathString));
			if (!f.exists()){
				try {
					f.create(false, true, InitProject.PROGRESSMONITOR);
				} catch (CoreException e) {
					Log.gotUnexpectedExection("GenForClass", "generatedCode","", e);
				}
			}
		}

		IFile file = project.getFile(new Path(pathString + "/" + className
				+ ".java"));
		if (file.exists()) {
			for (int i = 1;; i++) {
				file = project.getFile(new Path(pathString + "/" + className
						+ i + ".java"));
				if (!file.exists()) {
					createAndOpen(file, c, packageName, className + i);
					break;
				}
			}
		} else
			createAndOpen(file, c, packageName, className);
	}
	
	private void createAndOpen(IFile file,Class c,String packageName,String className){

		JUnitGenerator tesrer = new JUnitGenerator(c,packageName,className);
		String source = tesrer.getCode().toString();
		IDocument d = new Document(source);
		CodeFormatter cf = ToolFactory.createCodeFormatter(javaProject.getOptions(true));
		TextEdit te = cf.format(
				CodeFormatter.K_COMPILATION_UNIT, source, 0, source.length(), 0, null);
		
		try {
			te.apply(d);
			source = d.get();
		} catch (Exception e) {
			Log.gotUnexpectedExection("GenForClass", "createAndOpen", "",e);
		}
		
		try {
			file.create(new ByteArrayInputStream(source.getBytes()), false, InitProject.PROGRESSMONITOR);
			IWorkbench wb= PlatformUI.getWorkbench();
			IEditorRegistry ier = wb.getEditorRegistry();
			IEditorDescriptor ied = ier.getDefaultEditor(file.getName());
			IWorkbenchWindow dw = wb.getActiveWorkbenchWindow();
			IWorkbenchPage page = dw.getActivePage();
			IEditorInput iei = new FileEditorInput(file);
			if (page != null){
				page.openEditor(iei,ied.getId(),true);
			}
		} catch (CoreException e) {
			Log.gotUnexpectedExection("GenForClass", "createAndOpen", "",e);
		}
	}
}
